<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Vue | V前端技术笔记</title>
    <meta name="generator" content="VuePress 1.5.2">
    
    <meta name="description" content="V前端技术笔记">
    <link rel="preload" href="/vv/assets/css/0.styles.4e101ab7.css" as="style"><link rel="preload" href="/vv/assets/js/app.ae00cca3.js" as="script"><link rel="preload" href="/vv/assets/js/2.5eb07d41.js" as="script"><link rel="preload" href="/vv/assets/js/11.f6ed8906.js" as="script"><link rel="prefetch" href="/vv/assets/js/10.e0bab49e.js"><link rel="prefetch" href="/vv/assets/js/12.aaeaa660.js"><link rel="prefetch" href="/vv/assets/js/3.b85f619c.js"><link rel="prefetch" href="/vv/assets/js/4.94268aed.js"><link rel="prefetch" href="/vv/assets/js/5.b71de90c.js"><link rel="prefetch" href="/vv/assets/js/6.4e4b8e3f.js"><link rel="prefetch" href="/vv/assets/js/7.78b8735e.js"><link rel="prefetch" href="/vv/assets/js/8.6d0594c7.js"><link rel="prefetch" href="/vv/assets/js/9.3be1daac.js">
    <link rel="stylesheet" href="/vv/assets/css/0.styles.4e101ab7.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/vv/" class="home-link router-link-active"><!----> <span class="site-name">V前端技术笔记</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/vv/html/" class="nav-link">
  HTML
</a></div><div class="nav-item"><a href="/vv/css/" class="nav-link">
  CSS
</a></div><div class="nav-item"><a href="/vv/js/" class="nav-link">
  JavaScript
</a></div><div class="nav-item"><a href="/vv/vue/" aria-current="page" class="nav-link router-link-exact-active router-link-active">
  Vue
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Language Menu" class="dropdown-title"><span class="title">其他</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/vv/webpack/" class="nav-link">
  Webpack
</a></li><li class="dropdown-item"><!----> <a href="/vv/network/" class="nav-link">
  网络
</a></li><li class="dropdown-item"><!----> <a href="/vv/interview/" class="nav-link">
  面试题
</a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/vv/html/" class="nav-link">
  HTML
</a></div><div class="nav-item"><a href="/vv/css/" class="nav-link">
  CSS
</a></div><div class="nav-item"><a href="/vv/js/" class="nav-link">
  JavaScript
</a></div><div class="nav-item"><a href="/vv/vue/" aria-current="page" class="nav-link router-link-exact-active router-link-active">
  Vue
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Language Menu" class="dropdown-title"><span class="title">其他</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/vv/webpack/" class="nav-link">
  Webpack
</a></li><li class="dropdown-item"><!----> <a href="/vv/network/" class="nav-link">
  网络
</a></li><li class="dropdown-item"><!----> <a href="/vv/interview/" class="nav-link">
  面试题
</a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Vue</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/vv/vue/#_1-vue的优点" class="sidebar-link">1.vue的优点</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_2-请详细说下你对vue生命周期的理解" class="sidebar-link">2.请详细说下你对vue生命周期的理解</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_3-为什么vue组件中data必须是一个函数" class="sidebar-link">3.为什么vue组件中data必须是一个函数</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_4-vue数据双向绑定原理；" class="sidebar-link">4.vue数据双向绑定原理；</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_5-vue-computed原理、computed和watch的区别；" class="sidebar-link">5.vue computed原理、computed和watch的区别；</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#计算属性computed：" class="sidebar-link">计算属性computed：</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#侦听属性watch：" class="sidebar-link">侦听属性watch：</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_4-mvvm模式、mvc模式理解；" class="sidebar-link">4.mvvm模式、mvc模式理解；</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#简述-mvvm" class="sidebar-link">简述 MVVM</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_5-v-on可以监听多个方法吗？" class="sidebar-link">5.v-on可以监听多个方法吗？</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_6-vue如何获取dom" class="sidebar-link">6.vue如何获取dom</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_7-assets和static的区别" class="sidebar-link">7.assets和static的区别</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_8-vue初始化页面的闪动" class="sidebar-link">8.vue初始化页面的闪动</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_9-vuex中有几个核心属性，分别是什么？" class="sidebar-link">9.vuex中有几个核心属性，分别是什么？</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_10-vuex中的数据在页面刷新后数据消失" class="sidebar-link">10.vuex中的数据在页面刷新后数据消失</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_11-vue-router" class="sidebar-link">11.vue-router</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_12-vue-router导航钩子" class="sidebar-link">12.vue-router导航钩子</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_13-vue路由传参" class="sidebar-link">13.vue路由传参</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/vv/vue/#_14-router和route的区别" class="sidebar-link">14.router和route的区别</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="vue"><a href="#vue" class="header-anchor">#</a> Vue</h1> <h2 id="_1-vue的优点"><a href="#_1-vue的优点" class="header-anchor">#</a> 1.vue的优点</h2> <ul><li>轻量级框架</li> <li>简单易学</li> <li>双向数据绑定</li> <li>组件化</li> <li>视图，数据，结构分离</li> <li>虚拟dom</li> <li>运行速度快</li></ul> <h2 id="_2-请详细说下你对vue生命周期的理解"><a href="#_2-请详细说下你对vue生命周期的理解" class="header-anchor">#</a> 2.请详细说下你对vue生命周期的理解</h2> <blockquote><p>总共8个阶段，创建前/后，载入前/后，更新前/后，销毁前/后。</p></blockquote> <ul><li>创建前/后： 在<strong>beforeCreate</strong>阶段，vue实例的挂载元素el和数据对象data都为undefined，还未初始化。在<strong>created</strong>阶段，vue实例的数据对象data有了，el为undefined，还未初始化。</li> <li>载入前/后：在<strong>beforeMount</strong>阶段，vue实例的$el和data都初始化了，但还是挂载之前为虚拟的dom节点，data.message还未替换。在<strong>mounted</strong>阶段，vue实例挂载完成，data.message成功渲染。</li> <li>更新前/后：当data变化时，会触发<strong>beforeUpdate</strong>和<strong>updated</strong>方法</li> <li>销毁前/后：在执行destroy方法后，对data的改变不会再触发周期函数，说明此时vue实例已经解除了事件监听以及和dom的绑定，但是dom结构依然存在</li></ul> <h2 id="_3-为什么vue组件中data必须是一个函数"><a href="#_3-为什么vue组件中data必须是一个函数" class="header-anchor">#</a> 3.为什么vue组件中data必须是一个函数</h2> <ul><li>对象为引用类型，当复用组件时，由于数据对象都指向同一个data对象，当在一个组件中修改data时，其他重用的组件中的data会同时被修改；而使用返回对象的函数，由于每次返回的都是一个新对象（Object的实例），引用地址不同，则不会出现这个问题。</li></ul> <h2 id="_4-vue数据双向绑定原理；"><a href="#_4-vue数据双向绑定原理；" class="header-anchor">#</a> 4.vue数据双向绑定原理；</h2> <p>vue.js 是采用数据劫持结合发布者-订阅者模式的方式，通过Object.defineProperty()来劫持各个属性的setter，getter，在数据变动时发布消息给订阅者，触发相应的监听回调。主要分为以下几个步骤：</p> <blockquote><p>1、需要observe的数据对象进行递归遍历，包括子属性对象的属性，都加上setter和getter这样的话，给这个对象的某个值赋值，就会触发setter，那么就能监听到了数据变化</p></blockquote> <blockquote><p>2、compile解析模板指令，将模板中的变量替换成数据，然后初始化渲染页面视图，并将每个指令对应的节点绑定更新函数，添加监听数据的订阅者，一旦数据有变动，收到通知，更新视图</p></blockquote> <blockquote><p>3、Watcher订阅者是Observer和Compile之间通信的桥梁，主要做的事情是: ①在自身实例化时往属性订阅器(dep)里面添加自己 ②自身必须有一个update()方法 ③待属性变动dep.notice()通知时，能调用自身的update()方法，并触发Compile中绑定的回调，则功成身退。</p></blockquote> <blockquote><p>4、MVVM作为数据绑定的入口，整合Observer、Compile和Watcher三者，通过Observer来监听自己的model数据变化，通过Compile来解析编译模板指令，最终利用Watcher搭起Observer和Compile之间的通信桥梁，达到数据变化 -&gt; 视图更新；视图交互变化(input) -&gt; 数据model变更的双向绑定效果。</p></blockquote> <h2 id="_5-vue-computed原理、computed和watch的区别；"><a href="#_5-vue-computed原理、computed和watch的区别；" class="header-anchor">#</a> 5.vue computed原理、computed和watch的区别；</h2> <h2 id="计算属性computed："><a href="#计算属性computed：" class="header-anchor">#</a> 计算属性computed：</h2> <ul><li><p>支持缓存，只有依赖数据发生改变，才会重新进行计算</p></li> <li><p>不支持异步，当computed内有异步操作时无效，无法监听数据的变化</p></li> <li><p>computed 属性值会默认走缓存，计算属性是基于它们的响应式依赖进行缓存的，也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值</p></li> <li><p>如果一个属性是由其他属性计算而来的，这个属性依赖其他属性，是一个多对一或者一对一，一般用computed</p></li> <li><p>如果computed属性属性值是函数，那么默认会走get方法；函数的返回值就是属性的属性值；在computed中的，属性都有一个get和一个set方法，当数据变化时，调用set方法。</p> <h2 id="侦听属性watch："><a href="#侦听属性watch：" class="header-anchor">#</a> 侦听属性watch：</h2></li> <li><p>不支持缓存，数据变，直接会触发相应的操作；</p></li> <li><p>watch支持异步；</p></li> <li><p>监听的函数接收两个参数，第一个参数是最新的值；第二个参数是输入之前的值；</p></li> <li><p>当一个属性发生变化时，需要执行对应的操作；一对多；</p></li> <li><p>监听数据必须是data中声明过或者父组件传递过来的props中的数据，当数据变化时，触发其他操作，函数有两个参数：</p></li></ul> <h2 id="_4-mvvm模式、mvc模式理解；"><a href="#_4-mvvm模式、mvc模式理解；" class="header-anchor">#</a> 4.mvvm模式、mvc模式理解；</h2> <p>『View』：视图层（UI 用户界面）
『ViewModel』：业务逻辑层（一切 js 可视为业务逻辑）
『Model』：数据层（存储数据及对数据的处理如增删改查）</p> <ul><li>MVVM 将数据双向绑定（data-binding）作为核心思想，View 和 Model 之间没有联系，它们通过 ViewModel 这个桥梁进行交互。</li> <li>Model 和 ViewModel 之间的交互是双向的，因此 View 的变化会自动同步到 Model，而 Model 的变化也会立即反映到 View 上显示。</li> <li>当用户操作 View，ViewModel 感知到变化，然后通知 Model 发生相应改变；反之当 Model 发生改变，ViewModel 也能感知到变化，使 View 作出相应更新。</li></ul> <h2 id="简述-mvvm"><a href="#简述-mvvm" class="header-anchor">#</a> 简述 MVVM</h2> <ul><li>MVVM 是 Model-View-ViewModel 的缩写。MVVM 是一种设计思想。Model 层代表数据模型，也可以在 Model 中定义数据修改和操作的业务逻辑；View 代表 UI 组件，它负责将数据模型转化成 UI 展现出来，ViewModel 是一个同步 View 和 Model 的对象。</li> <li>在 MVVM 架构下，View 和 Model 之间并没有直接的联系，而是通过 ViewModel 进行交互，Model 和 ViewModel 之间的交互是双向的， 因此 View 数据的变化会同步到 Model 中，而 Model 数据的变化也会立即反应到 View 上。</li> <li>ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来，而View 和 Model 之间的同步工作完全是自动的，无需人为干涉，因此开发者只需关注业务逻辑，不需要手动操作DOM, 不需要关注数据状态的同步问题，复杂的数据状态维护完全由 MVVM 来统一管理。</li></ul> <h2 id="_5-v-on可以监听多个方法吗？"><a href="#_5-v-on可以监听多个方法吗？" class="header-anchor">#</a> 5.v-on可以监听多个方法吗？</h2> <p>可以</p> <h2 id="_6-vue如何获取dom"><a href="#_6-vue如何获取dom" class="header-anchor">#</a> 6.vue如何获取dom</h2> <p>ref 通过this.$refs.test</p> <h2 id="_7-assets和static的区别"><a href="#_7-assets和static的区别" class="header-anchor">#</a> 7.assets和static的区别</h2> <ul><li>这两个都是用来存放项目中所使用的静态资源文件。</li> <li>两者的区别：</li> <li>assets中的文件在运行npm run build的时候会打包，简单来说就是会被压缩体积，代码格式化之类的。打包之后也会放到static中。</li> <li>static中的文件则不会被打包。</li></ul> <blockquote><p>建议：将图片等未处理的文件放在assets中，打包减少体积。而对于第三方引入的一些资源文件如iconfont.css等可以放在static中，因为这些文件已经经过处理了。</p></blockquote> <h2 id="_8-vue初始化页面的闪动"><a href="#_8-vue初始化页面的闪动" class="header-anchor">#</a> 8.vue初始化页面的闪动</h2> <div class="language-css line-numbers-mode"><pre class="language-css"><code><span class="token selector">[v-cloak]</span><span class="token punctuation">{</span>
	<span class="token property">display</span><span class="token punctuation">:</span>none
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><blockquote><p>如果没有彻底解决问题，则在根元素加上style=&quot;display: none;&quot; :style=&quot;{display: 'block'}&quot;</p></blockquote> <h2 id="_9-vuex中有几个核心属性，分别是什么？"><a href="#_9-vuex中有几个核心属性，分别是什么？" class="header-anchor">#</a> 9.vuex中有几个核心属性，分别是什么？</h2> <p>一共有5个核心属性，分别是:</p> <ol><li>state 唯一数据源,Vue 实例中的 data 遵循相同的规则</li> <li>getters 可以认为是 store 的计算属性,就像计算属性一样，getter 的返回值会根据它的依赖被缓存起来，且只有当它的依赖值发生了改变才会被重新计算。Getter 会暴露为 store.getters 对象，你可以以属性的形式访问这些值.</li> <li>mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,非常类似于事件,通过store.commit 方法触发</li> <li>action Action 类似于 mutation，不同在于Action 提交的是 mutation，而不是直接变更状态，Action 可以包含任意异步操作</li> <li>module 由于使用单一状态树，应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时，store 对象就有可能变得相当臃肿。为了解决以上问题，Vuex 允许我们将 store 分割成模块（module）</li></ol> <h2 id="_10-vuex中的数据在页面刷新后数据消失"><a href="#_10-vuex中的数据在页面刷新后数据消失" class="header-anchor">#</a> 10.vuex中的数据在页面刷新后数据消失</h2> <p>​	用sessionstorage 或者 localstorage 存储数据</p> <h2 id="_11-vue-router"><a href="#_11-vue-router" class="header-anchor">#</a> 11.vue-router</h2> <p>Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成，让构建单页面应用变得易如反掌。包含的功能有：</p> <ul><li>嵌套的路由/视图表</li> <li>模块化的、基于组件的路由配置</li> <li>路由参数、查询、通配符</li> <li>基于 Vue.js 过渡系统的视图过渡效果</li> <li>细粒度的导航控制</li> <li>带有自动激活的 CSS class 的链接</li> <li>HTML5 历史模式或 hash 模式，在 IE9 中自动降级</li> <li>自定义的滚动条行为</li></ul> <h2 id="_12-vue-router导航钩子"><a href="#_12-vue-router导航钩子" class="header-anchor">#</a> 12.vue-router导航钩子</h2> <p>​	常用的是router.beforeEach(to,from,next)，在跳转前进行权限判断。一共有三种：</p> <ul><li>全局导航钩子：router.beforeEach(to,from,next)</li> <li>组件内的钩子</li> <li>单独路由独享组件</li></ul> <h2 id="_13-vue路由传参"><a href="#_13-vue路由传参" class="header-anchor">#</a> 13.vue路由传参</h2> <blockquote><p>使用query方法传入的参数使用this.$route.query接受</p></blockquote> <blockquote><p>使用params方式传入的参数使用this.$route.params接受</p></blockquote> <h2 id="_14-router和route的区别"><a href="#_14-router和route的区别" class="header-anchor">#</a> 14.router和route的区别</h2> <blockquote><p><strong>route</strong> 为当前router跳转对象里面可以获取name、path、query、params等</p></blockquote> <blockquote><p><strong>router</strong> 为VueRouter实例，想要导航到不同URL，则使用router.push方法</p></blockquote></div> <footer class="page-edit"><!----> <!----></footer> <!----> </main></div><div class="global-ui"></div></div>
    <script src="/vv/assets/js/app.ae00cca3.js" defer></script><script src="/vv/assets/js/2.5eb07d41.js" defer></script><script src="/vv/assets/js/11.f6ed8906.js" defer></script>
  </body>
</html>
